home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 15 / CU Amiga Magazine's Super CD-ROM 15 (1997)(EMAP Images)(GB)[!][issue 1997-10].iso / CUCD / Utilities / Post / Source / Iff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-01  |  6.9 KB  |  305 lines

  1. /* IFF ILBM routines */
  2. /* NOTE: This only works if you link with libnix. It fails with ixemul        *
  3. because ixemul.library is opened by the maintask and iffpage is called        *
  4. by the subtask. The problem are the file-commands which should be replaced    *
  5. by Amigados-commands (Open(), Write()...) or you link with libnix             */
  6.  
  7. #include "PostPre.h"
  8. #include "Global.h"
  9.  
  10. extern    int    page_counter;
  11. extern    BPTR    outfh;
  12.  
  13. int                iffseq = 0;
  14. static int        newpage=TRUE, counter, end, ifferr, xa, ya, i,
  15.                     j, k, ch, fslen;
  16. static long        addr1, addr2;
  17. static UWORD    w;
  18. static char        fname[110], fsnum[10];
  19. static FILE        *ifffptr;
  20.  
  21. /* Find the greatest common divisor of two positive integers.  If one is
  22.  * zero the result is the other */
  23.  
  24. int igcd(int n, int m)
  25. {   unsigned int n1, m1, r;
  26.     if      (n > m)
  27.     {   n1 = n;
  28.         m1 = m;
  29.     }
  30.     else if (m > n)
  31.     {   n1 = m;
  32.         m1 = n;
  33.     }
  34.     else
  35.         return n;
  36.     while (m1 != 0)
  37.     {   r = n1 % m1;
  38.         n1 = m1;
  39.         m1 = r;
  40.     }
  41.     return (int) n1;
  42. }
  43.  
  44. /* Put a byte */
  45.  
  46. static void iffputb(int b)
  47. {   if (ifferr) return;
  48.     if (putc((int) b, ifffptr) == EOF)
  49.     {   ifferr = 1;
  50.         return;
  51.     }
  52. }
  53.  
  54. /* Put a word */
  55.  
  56. static void iffputw(int w)
  57. {   iffputb(w>>8);
  58.     iffputb(w);
  59. }
  60.  
  61. /* Put a long */
  62.  
  63. static void iffputl(int l)
  64. {   iffputb(l>>24);
  65.     iffputb(l>>16);
  66.     iffputb(l>>8);
  67.     iffputb(l);
  68. }
  69.  
  70. /* Put a string */
  71.  
  72. static void iffputs(char *str)
  73. {   while (*str) iffputb(*str++);
  74. }
  75.  
  76. /* Pack a bitmap row */
  77.  
  78. static void iffpack(char *buf, int len)
  79. {   int b, c, l;
  80.     if (ifferr) return;
  81.     l = 0;
  82.     while (len--)
  83.     {   b = *buf++;                  /* Pick up a byte */
  84.         c = 1;
  85.         while (len && *buf == b && c < 128)
  86.         {   c++;
  87.             buf++;
  88.             len--;                   /* See if it begins a run */
  89.         }
  90.         if (c == 2 &&                /* If a two byte run */
  91.             l > 0 &&                 /*    and preceeded by literals */
  92.             l <= 125 &&              /*    and not more than 125 of them */
  93.             (len <= 2 ||             /*    and no more than 2 bytes left */
  94.              *buf != *(buf + 1)))    /*        or not followed by a run */
  95.         {   c = 1;                   /* Then make it a literal */
  96.             buf--;
  97.             len++;
  98.         }
  99.         if (c == 1)                  /* If not a run */
  100.         {   l++;                     /* Then it must be a literal */
  101.             c = 0;
  102.         }
  103.         if (l > 0 &&                 /* If we have some literals */
  104.             (c > 1 ||                /*    and beginning a run */
  105.              l == 127 ||             /*    or reached 127 */
  106.              len == 0))              /*    or no more bytes left */
  107.         {   if (putc((unsigned char) (l - 1), ifffptr) == EOF)
  108.             {   ifferr = 1;
  109.                 return;
  110.             }
  111.             while (l)              /* Then write out  the literals */
  112.             {   if (putc((unsigned char) *(buf - c - l), ifffptr) == EOF)
  113.                 {   ifferr = 1;
  114.                     return;
  115.                 }
  116.                 l--;
  117.             }
  118.         }
  119.         if (c > 1)                   /* If we have a run, write it */
  120.         {   if (putc((unsigned char) (1-c), ifffptr) == EOF)
  121.             {   ifferr = 1;
  122.                 return;
  123.             }
  124.             if (putc((unsigned char) b, ifffptr) == EOF)
  125.             {   ifferr = 1;
  126.                 return;
  127.             }
  128.         }
  129.     }
  130. }
  131.  
  132. /* Determine the current address */
  133.  
  134. static long ifftell(void)
  135. {   long addr;
  136.     if (ifferr) return 0;
  137.     if ((addr = ftell(ifffptr)) == -1)
  138.     {   ifferr = 1;
  139.         return 0;
  140.     }
  141.     return addr;
  142. }
  143.  
  144. /* Fix up the length of a chunk */
  145.  
  146. static void ifffixup(long addr)
  147. {   long size;
  148.     if (ifferr) return;
  149.     if ((size = ftell(ifffptr)) == -1)
  150.     {   ifferr = 1;
  151.         return;
  152.     }
  153.     if (size & 1) iffputb(0);
  154.     size = size - addr - 8;
  155.     if (fseek(ifffptr, addr + 4, 0) != 0)
  156.     {   ifferr = 1;
  157.         return;
  158.     }
  159.     iffputl(size);
  160.     if (fseek(ifffptr, 0, 2) != 0)
  161.     {   ifferr = 1;
  162.         return;
  163.     }
  164. }
  165.  
  166. /* Write the page to the iff output file */
  167.  
  168. void iffpage(struct BitMap *my_iff_bm)
  169. {
  170.  
  171. /* Compute the aspect ratio.  Make sure the values fit into a byte */
  172.  
  173.     xa = parm.page.yden;
  174.     ya = parm.page.xden;
  175.     i = igcd(xa, ya);
  176.     xa /= i;
  177.     ya /= i;
  178.     while (xa > 255 && ya > 255)
  179.     {
  180.         xa /= 2;
  181.         ya /= 2;
  182.     }
  183.  
  184. /* Construct the file name.  Copy it, replacing "*" by the sequence
  185.  * number.  The scan it backwards replacing "?" by digits */
  186.  
  187.     if(newpage)
  188.     {
  189.         i = iffseq;
  190.         iffseq++;
  191.         fslen = 0;
  192.         while (i)
  193.         {
  194.             fsnum[fslen++] = i % 10 + '0';
  195.             i /= 10;
  196.         }
  197.         i = j = 0;
  198.         for (;;)
  199.         {
  200.             if (j > 100)
  201.             {
  202.                 ioerror = errioerror;
  203.                 return;
  204.             }
  205.             ch = Options.PostOpts.iffname[i++];
  206.             if (ch == '*')
  207.             {
  208.                 k = fslen;
  209.                 while (k--) fname[j++] = fsnum[k];
  210.             }
  211.             else fname[j++] = ch;
  212.             if (ch == 0) break;
  213.         }
  214.         k = 0;
  215.         while (--j)
  216.         {
  217.             if (fname[j] == '?') fname[j] = (k < fslen) ? fsnum[k++] : '0';
  218.         }
  219.     }
  220.  
  221.     if(argverbose && !argwindow)
  222.     {
  223.         FPrintf(outfh, " to iff-file '%s' ... ", (ULONG) fname);
  224.         Flush(outfh);
  225.     }
  226.  
  227. /* Open the file, write a FORM ILBM, and close it again */
  228.  
  229.     if(newpage)
  230.     {
  231.         ifferr = 0;
  232.         ifffptr = fopen(fname, "wb");
  233.         if (ifffptr == NULL) ifferr = 1;
  234.  
  235.         addr1 = ifftell();
  236.         iffputs("FORM");          /* FORM ILBM */
  237.         iffputl(0);
  238.         iffputs("ILBM");
  239.  
  240.         iffputs("BMHD");          /* BMHD */
  241.         iffputl(20);
  242.         iffputw(parm.page.xsize); /* Width */
  243.         iffputw(parm.page.yheight); /* Height */
  244.         iffputw(0);               /* X position */
  245.         iffputw(0);               /* Y position */
  246.         iffputb(parm.page.depth); /* Number of bit planes */
  247.         iffputb(0);               /* Masking:     None */
  248.         iffputb(1);               /* Compression: ByteRun */
  249.         iffputb(0);               /* Pad1 */
  250.         iffputw(0);               /* Transparent colour */
  251.         iffputb(xa);              /* X aspect */
  252.         iffputb(ya);              /* Y aspect */
  253.         iffputw(parm.page.xsize); /* Source width */
  254.         iffputw(parm.page.yheight); /* Source height */
  255.  
  256.         addr2 = ifftell();
  257.         iffputs("CMAP");          /* CMAP */
  258.         iffputl(0);
  259.         for (i = 0; i < colormap.Count; i++)
  260.         {
  261.             w = ((UWORD *) colormap.ColorTable)[i];
  262.             iffputb(((w >> 8) & 15) << 4);
  263.             iffputb(((w >> 4) & 15) << 4);
  264.             iffputb(( w       & 15) << 4);
  265.         }
  266.         ifffixup(addr2);
  267.  
  268.         iffputs("CAMG");      /* CAMG */
  269.         iffputl(4);
  270.         iffputl(Options.Screen.ScrDisplayID);
  271.  
  272.         addr2 = ifftell();
  273.         iffputs("BODY");          /* BODY */
  274.         iffputl(0);
  275.  
  276.         counter = 0;
  277.     }
  278.  
  279.     end = my_iff_bm->Rows;
  280.     counter += my_iff_bm->Rows;
  281.     if(counter < parm.page.yheight)
  282.     {
  283.         newpage = FALSE;
  284.     }
  285.     else
  286.     {
  287.         newpage = TRUE;
  288.         end -= counter-parm.page.yheight;
  289.     }
  290.  
  291.     for (j = 0; j < end; j++)
  292.         for (i = 0; i < my_iff_bm->Depth; i++)
  293.             iffpack((char *) my_iff_bm->Planes[i] + j * my_iff_bm->BytesPerRow,
  294.                         my_iff_bm->BytesPerRow);
  295.  
  296.     fflush(ifffptr);
  297.     if(newpage)
  298.     {
  299.         ifffixup(addr2);
  300.         ifffixup(addr1);
  301.         if (fclose(ifffptr) == EOF) ifferr = 1;
  302.     }
  303.     if (ifferr) ioerror = errioerror;
  304. }
  305.